package myJs.browse

import myJs.Implicits._
import myJs.api.Api
import myJs.cps.BootstrapTableCp.Column
import myJs.cps._
import myJs.myPkg._
import myJs.search.Search
import myJs.search.detail.Detail
import myJs.tool.Pojo._
import myJs.tool.Tool
import org.scalajs.dom.{Event, html}
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import slinky.core.{FunctionalComponent, SyntheticEvent, TagElement}
import slinky.core.annotations.react
import slinky.core.facade.Hooks._
import slinky.web.html._
import upickle.default._

import scala.collection.immutable.SeqMap

/**
 * Created by yz on 21/1/2022
 */
@react object MlRnaCp {

  case class Props(geneType: String)

  val component = FunctionalComponent[Props] { props =>

    val geneTypeMap = List("protein-coding", "lncRNA").optionMap
    val initGeneTypeCheckedMap = geneTypeMap.map { case (k, v) =>
      (k, false)
    }
    val speciesMap = List("Hsa", "Mmu").optionMap
    val initSpeciesCheckedMap = speciesMap.map { case (k, v) =>
      (k, false)
    }

    val (datas, setDatas) = useState(List.empty[ujson.Obj])
    val (columns, setColumns) = useState(List.empty[Column])
    val (refresh, setRefresh) = useState(false)
    val (geneTypeCheckedMap, setGeneTypeCheckedMap) = useState(initGeneTypeCheckedMap)
    val (speciesCheckedMap, setSpeciesCheckedMap) = useState(initSpeciesCheckedMap)

    useEffect(() => {
      FTool.refreshColumns()
    }, List()
    )

    object FTool {

      def refreshColumns = () => {
        val select2Keys = List("species", "geneType")
        val data = ujson.Obj(
          "keys" -> select2Keys
        )
        val dataStr = write(data)
        Api.getSelect2Values(dataStr).map { rs =>
          val fieldOptionMap = rs.map { case (k, v) =>
            val inputName = k
            val data = v.toJArS.toList
            (inputName, data)
          }.toList.toSeqMap

          val map = SeqMap(
            "geneSymbol"->"Gene Symbol",
            "species"->"Species",
            "geneType"->"Gene Type",
            "geneId"->"Gene ID",
            "related"->"Related circRNA",
            "fetalMedian"->"Fetal Median",
            "fetalFreq"->"Fetal Freq",
            "normalMedian"->"Normal Median",
            "normalFreq"->"Normal Freq",
            "fattyLiverMedian"->"Fatty Liver Median",
            "fattyIverFreq"->"Fatty Liver Freq",
            "nafldMedian"->"NAFLD Median",
            "nafldFreq"->"NAFLD Freq",
            "aldMedian"->"ALD Median",
            "aldFreq"->"ALD Freq",
            "vhMedian"->"Viral Hepatitis Median",
            "vhFreq"->"Viral Hepatitis Freq",
            "fibrosisMedian"->"Fibrosis Median",
            "fibrosisFreq"->"Fibrosis Freq",
            "cirrhosisMedian"->"Cirrhosis Median",
            "cirrhosisFreq"->"Cirrhosis Freq",
            "dnMedian"->"Dysplastic Nodule Median",
            "dnFreq"->"Dysplastic Nodule Freq",
            "hccMedian"->"HCC Median",
            "hccFreq"->"HCC Freq",
            "fibrolamellarMedian"->"Fibrolamellar Median",
            "fibrolamellarFreq"->"Fibrolamellar Freq",
            "iccMedian"->"ICC Median",
            "iccFreq"->"ICC Freq",
            "mixedMedian"->"Mixed HCC-ICC Median",
            "mixedFreq"->"Mixed HCC-ICC Freq",
            "hbMedian"->"HB Median",
            "hbFreq"->"HB Freq",
          )
          val basicColumns = map.map { case (k, v) =>
            val searchKind = k match {
              case x if (x.endsWith("Median") || x.endsWith("Freq")) => DoubleSearch
              case x if select2Keys.contains(x) => CheckboxSearch
              case _ => TextSearch
            }
            val title = v match {
              case _ => v
            }
            val operable = k match {
              case "geneType" | "species" => false
              case _ => true
            }
            val fmt = FTool.tbFmt(k)
            val comVF = FTool.comVFmt(v)
            val optionMap = searchKind match {
              case CheckboxSearch => fieldOptionMap(k).optionMap
              case _ => SeqMap[String, String]()
            }
            val defaultValue = v match {
              case "Gene Type" => props.geneType
              case _ => ""
            }
            Column(field = k, title = title, operable = operable, searchKind = searchKind, formatter = fmt,
              comVF = comVF, optionMap = optionMap, defaultValue = defaultValue)
          }.toList
          setColumns(basicColumns)
        }
      }

      def tbFmt(field: String) = (v: ujson.Value, row: ujson.Obj) => {
        field match {
          case "geneSymbol" =>
            val url = s"#${Detail.absolutePath}"
            a(target := "_blank", href := s"${url}?geneName=${v.str}&species=${row("species").str}", s"${v.str}")()
          case "related"=>
            val url = s"${Search.absolutePath}?geneName=${row("geneSymbol").str}&tab=circRna"
            if(v.str=="NA"){
              span(v.str)()
            }else{
              a(target := "_blank", href := url, s"${v.str}")()
            }
          case _ => val vStr = v.myStr
            span(vStr)()
        }
      }

      def comVFmt(fileTitle: String) = (v: ujson.Value, row: ujson.Obj) => {
        fileTitle match {
          case _ => v.myStr
        }
      }

      def dbFmt(v: String) = {
        if (v.isDouble) {
          ujson.Num(v.toDouble)
        } else {
          ujson.Str(v)
        }
      }

      def ajaxRequest = (limit: Int, offset: Int,
                         searchMap: SeqMap[String, SearchData], sortDataOp: Option[SortData], allSearch: String) => {
        val options = Tool.layerOptions.copy(shade = List("0.1", "#fff"))
        val index = layer.load(0, options)
        val trueSortObj = if (sortDataOp.isEmpty) {
          ujson.Obj()
        } else {
          val sortData = sortDataOp.get
          ujson.Obj("sort" -> ujson.Obj(
            "field" -> sortData.field,
            "kind" -> sortData.kind,
            "order" -> sortData.order,
          ))
        }
        val searchs = searchMap.map { case (k, searchData) =>
          searchData match {
            case TextSearchData(searchType, text) =>
              ujson.Obj(
                "name" -> k,
                "kind" -> "text",
                "searchType" -> searchType,
                "value" -> text,
              )
            case NumericSearchData(min, max, kind) =>
              ujson.Obj(
                "name" -> k,
                "kind" -> kind,
                "min" -> dbFmt(min),
                "max" -> dbFmt(max),
              )
            case CheckboxSearchData(values) =>
              ujson.Obj(
                "name" -> k,
                "kind" -> "checkbox",
                "value" -> values,
              )
          }
        }.toList
        val geneTypeSearch = {
          val values = geneTypeCheckedMap.filter(_._2).map(_._1)
          if (values.isEmpty) {
            ujson.Obj()
          } else {
            ujson.Obj(
              "name" -> "geneType",
              "kind" -> "checkbox",
              "value" -> values,
            )
          }

        }
        val speciesSearch = {
          val values = speciesCheckedMap.filter(_._2).map(_._1)
          if (values.isEmpty) {
            ujson.Obj()
          } else {
            ujson.Obj(
              "name" -> "species",
              "kind" -> "checkbox",
              "value" -> values,
            )
          }
        }
        val formSearchs = List(
          geneTypeSearch, speciesSearch
        ).filter { obj =>
          obj.value.nonEmpty
        }
        val trueSearchObj = ujson.Obj("search" -> (searchs ::: formSearchs))
        val obj = ujson.Obj(
          "limit" -> limit,
          "offset" -> offset,
          "allSearch" -> allSearch
        ) ++ trueSortObj ++ trueSearchObj
        val dataStr = write(obj)
        Api.allByServer(dataStr).map { obj =>
          layer.close(index)
          obj
        }

      }

      def search = () => {
        setRefresh(true)
      }

      def refreshChange = (v: Boolean) => {
        setRefresh(v)
      }

      def valueChange(k: String) = (e: SyntheticEvent[input.tagType#RefType, Event]) => {
        val input = e.target
        val checked = input.checked
        val curCheckedMap = geneTypeCheckedMap + (k -> checked)
        setGeneTypeCheckedMap(curCheckedMap)
      }

      def speciesChange(k: String) = (e: SyntheticEvent[input.tagType#RefType, Event]) => {
        val input = e.target
        val checked = input.checked
        val curCheckedMap = speciesCheckedMap + (k -> checked)
        setSpeciesCheckedMap(curCheckedMap)
      }

    }

    val exportDatas = List(
      ExportData("TXT", href = s"${Api.apiUrl}/gepLiver/tool/downloadFile?fileName=Browse_gene.txt")
    )

    div(
      div(style := Style(),

        form(className := "form-horizontal", id := "form",

          div(className := "myEachGroup form-group",
            label(className := "control-label col-sm-2", s"Gene Type:",
            ),
            div(className := "col-sm-10",
              geneTypeCheckedMap.map { case (k, isChecked) =>
                div(key := s"${k}", style := Style(paddingLeft = "0px", marginTop = 7), className := "col-sm-3",
                  input(
                    style := Style(marginRight = "7px"),
                    className := "basicInfo",
                    `type` := "checkbox",
                    name := "geneTypes[]",
                    value := k, checked := isChecked, onChange := FTool.valueChange(k),
                  ),
                  label(
                    className := "myCheckbox form-check-label",
                    k
                  )
                )
              }
            )
          ),

          div(className := "myEachGroup form-group",
            label(className := "control-label col-sm-2", s"Species:",
            ),
            div(className := "col-sm-10",
              speciesCheckedMap.map { case (k, isChecked) =>
                div(key := s"${k}", style := Style(paddingLeft = "0px", marginTop = 7), className := "col-sm-3",
                  input(
                    style := Style(marginRight = "7px"),
                    className := "basicInfo",
                    `type` := "checkbox",
                    name := "geneTypes[]",
                    value := k, checked := isChecked, onChange := FTool.speciesChange(k),
                  ),
                  label(
                    className := "myCheckbox form-check-label",
                    k
                  )
                )
              }
            )
          ),

          div(className := "form-group",
            div(className := "actions col-sm-offset-2 col-sm-3",
              button(style := Style(width = "95%"), `type` := "button", className := "btn btn-primary myAddShow",
                onClick := FTool.search,
                s" Search"
                ,
              ),
            ),
          ),

        ),

        hr(),

        div(
          BootstrapTableCp(columns = columns, datas = datas, pageList = List(10, 25, 50), pageSize = 10,
            sidePagination = "server", ajax = FTool.ajaxRequest, selectColumnEnabled = true, refresh = refresh,
            refreshChange = FTool.refreshChange, exportData=exportDatas,showExport = true,search = true)
        )

      ),
    )


  }

  object STool {

  }

}
